#include "stm32f4xx.h"                  // Device header
#include "stm32f4xx_conf.h"
#include <stdio.h>
#include <stdarg.h>

/**UART2(USART1)还复用RS485控制的TTL输入,故串口最好使用UART1(USART6)**/

//重定向串口选择,选择哪个串口就把哪个取消注释
#define UART1_Redirect//选择UART1重定向
//#define UART2_Redirect//选择UART2重定向

/*
 *函数简介:串口专用指数函数
 *参数说明:底数x
 *参数说明:指数y
 *返回类型:x^y
 *备注:x,y均为整数
 */
uint32_t USART_Pow(uint32_t x,uint32_t y)
{
	uint32_t Result=1;
	while(y--)
		Result*=x;
	return Result;
}

/*
 *函数简介:UART1串口发送初始化
 *参数说明:无
 *返回类型:无
 *备注:UART1为USART6,默认Tx引脚PG14
 */
void UART1_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);//开启时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化UART1-Tx(PG14)
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);//开启PG14的USART6复用模式
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate=115200;//配置波特率115200
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//配置无硬件流控制
	USART_InitStructure.USART_Mode=USART_Mode_Tx;//配置为发送模式
	USART_InitStructure.USART_Parity=USART_Parity_No;//配置为无校验位
	USART_InitStructure.USART_StopBits=USART_StopBits_1;//配置停止位为1
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;//配置字长8bit
	USART_Init(USART2,&USART_InitStructure);//初始化USART6
	
	USART_Cmd(USART2,ENABLE);//启动USART6
}

/*
 *函数简介:UART1发送一个字节
 *参数说明:8bits数据
 *返回类型:无
 *备注:无
 */
void UART1_SendByte(uint8_t Byte)
{
	USART_SendData(USART2,Byte);
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//等待发送完成
}

/*
 *函数简介:UART1发送一个数组
 *参数说明:8bits数组
 *参数说明:数组长度
 *返回类型:无
 *备注:无
 */
void UART1_SendArray(uint8_t *Array,uint16_t Length)
{
	for(uint16_t i=0;i<Length;i++)
		UART1_SendByte(Array[i]);//依次发送数组的每一位
}

/*
 *函数简介:UART1发送一个字符串
 *参数说明:字符串
 *返回类型:无
 *备注:无
 */
void UART1_SendString(char *String)
{
	for(uint8_t i=0;String[i]!='\0';i++)
		UART1_SendByte(String[i]);//依次发送字符串的每一位
}

/*
 *函数简介:UART1以文本形式发送一个数字
 *参数说明:整型数字
 *参数说明:数字长度(Length>=Number位数)
 *返回类型:无
 *备注:无
 */
void UART1_SendNumber(uint32_t Number,uint8_t Length)
{
	for(uint8_t i=0;i<Length;i++)
		UART1_SendByte(Number/USART_Pow(10,Length-i-1)%10+'0');//以文本形式发送数字每一位
}

#ifdef UART1_Redirect//选择UART1重定向
	/*
	 *函数简介:重写fputc函数(重定向printf，即移植printf)
	 *参数说明:无
	 *返回类型:无
	 *备注:看不懂
	 *备注:默认重定向UART1(即USART6),若想修改重定向串口,请更改最上方宏定义的注释
	 */
	int fputc(int ch,FILE *f)
	{
		USART2->DR=ch;
		while(!(USART2->SR&(1<<7))){}
		return ch;
	}

	/*
	 *函数简介:重写fgetc函数(重定向scanf，即移植scanf)
	 *参数说明:无
	 *返回类型:无
	 *备注:看不懂
	 *备注:默认重定向UART1(即USART6),若想修改重定向串口,请更改最上方宏定义的注释
	 */
	int fgetc(FILE *stream)
	{
		while(!(USART6->SR&1<<5)){}
		return USART6->DR;
	}
#endif
